/**
 * Application entry point
 */

// Load application styles
import 'styles/index.scss';

// ================================
// START YOUR APP HERE
// ================================

function dom(type, props, ...children) {

    return {
        type,
        props,
        children
    }
}

const types = {
    get:type => Object.prototype.toString.call(type),
    string: '[object String]',
    number: '[object Number]',
    array: '[object Array]',
    object: '[object Object]',
    function: '[object Function]',
    null: '[object Null]',
    undefined: '[object Undefined]',
    boolean:'[object Boolean]',
}

function isObjectChanged(obj1, obj2) {
    // 判断数据类型是否一致
    if (types.get(obj1) !== types.get(obj2))  {
        return true
    }

    // 两者都是object 深入判断
    if (types.get(obj1) === types.object) {
        const obj1Kyes = Object.keys(obj1)
        const obj2Keys = Object.keys(obj2)

        if (obj1Kyes.length !== obj2Keys.length) {
            return true
        }

        //长度相等，如果一个是0，那么属性肯定没有变化
        if (obj1Kyes.length === 0) {
            return false
        }

        for (let i = 0; i < obj1Kyes.length; i++) {
            let key = obj1Kyes[i]
            if (obj1[key] !== obj2[key]) {
                return true
            }
        }

    }

    return false
}

function generateDom(domObj) {
    let $el
    if (domObj.type) {
        $el = document.createElement(domObj.type)
    } else {
        $el = document.createTextNode(domObj)
    }

    if (domObj.props) {
        Object.keys(domObj.props).forEach(key => {
            $el.setAttribute(key,domObj.props[key])
        })
    }

    if (domObj.children) {
        domObj.children.forEach(child => {
            $el.appendChild(generateDom(child))
        })
    }

    return $el


}




function isNodeChanged(node1,node2) {
    if (node1.type !==undefined&& node2.type!==undefined) {
        return node1.type !==node2.type
    }

    return node1 !==node2
}


function vDom($parent, oldNode, newNode, index = 0) {
    const $currentNode = $parent.childNodes[index]
    if (!oldNode) {
        //append
        return $parent.append(generateDom(newNode))
    }
    if (!newNode) {
        //delete
        $parent.removeChild($currentNode)
    }

    //oldNode  newNode都有值

    if (isNodeChanged(oldNode, newNode)) {
        return $parent.replaceChild(generateDom(newNode),$currentNode)
    }

    // 两者为同样的字符串
    if (oldNode === newNode) {
        return
    }


    // 对比 props 更新

    if (isObjectChanged(oldNode.props, newNode.props)) {

        const oldProps = oldNode.props || {}
        const newProps = newNode.props || {}

        const oldPropsKeys = Object.keys(oldProps)
        const newPropsKeys = Object.keys(newProps)

        if (newPropsKeys.length === 0) {
            oldPropsKeys.forEach(prop=>{
                $currentNode.removeAttribute(prop)
            })
        } else {
            const allKeys = new Set([...oldPropsKeys, ...newPropsKeys])
            allKeys.forEach(prop=> {
                //没有old prop 需要设置新的prop
                if (oldProps[prop] === undefined) {
                    return $currentNode.setAttribute(prop, newProps[prop])
                }

                //没有new prop, 需要删除旧的
                if (newProps[prop] === undefined) {
                    return $currentNode.removeAttribute(prop)
                }

                //对比值是否一致
                if (oldProps[prop] !== newProps[prop]) {
                    return $currentNode.setAttribute(prop, newProps[prop])
                }
            })
        }
    }


    //循环对比子元素
    if ((oldNode.children && oldNode.children.length) ||
        (newNode.children && newNode.children.length)) {
        let maxLength = Math.max(oldNode.children.length, newNode.children.length)
        for (let i = 0; i < maxLength; i++) {
            vDom($currentNode,oldNode.children[i],newNode.children[i],i)
        }
    }

}

// const profile = <div id="profile" data-user-id="1"><p>赞恩</p></div>

const current = <div className={'profile'}>
   <div>
       <div>
           <span data-user-name={'zane'} className={'profile__username'}>赞恩老师</span>
       </div>
   </div>
</div>
const previous =null

const $app = document.querySelector('.app')
vDom($app, previous, current)

const nodeChanged = <div className={'profile'}>
    <div>
        <div>
            <span data-user-name={'tina'} className={'profile__active'}>tina</span>
        </div>
    </div>
</div>
setTimeout(() => {
    vDom($app, current, nodeChanged)
}, 3000)

console.log(current)



